package main

import (
	"fmt"
	"runtime"
	"sync"
	"time"

	"github.com/garyburd/redigo/redis"
)

// 它能够一直等到所有的goroutine执行完成，并且阻塞主线程的执行，直到所有的goroutine执行完成。
var w sync.WaitGroup

func newRdsPool(server, auth string) *redis.Pool {
	return &redis.Pool{
		MaxIdle:     100,
		MaxActive:   30,
		IdleTimeout: 60 * time.Second,
		Dial: func() (redis.Conn, error) {
			c, err := redis.Dial("tcp", server)
			if err != nil {
				return nil, err
			}
			if auth == "" {
				return c, err
			}
			if _, err := c.Do("AUTH", auth); err != nil {
				c.Close()
				return nil, err
			}
			return c, err
		},
		TestOnBorrow: func(c redis.Conn, t time.Time) error {
			_, err := c.Do("PING")
			return err
		},
	}
}

func g1(r redis.Conn) {
	r.Send("MULTI")
	fmt.Println(`g1 MULTI begin ...`)
	for i := 0; i < 5; i++ {
		if _, err := redis.String(r.Do("set", "hello", "10")); err != nil {
			fmt.Println(err)
		}
		fmt.Println(`g1 now work... `)
	}
	time.Sleep(1 * time.Second)
	r.Send("DEL", "hello")
	g, _ := r.Do("EXEC")
	fmt.Println(`g1 MULTI end ...`, g)
	// Done:相当于Add(-1)
	w.Done()
}

func g2(r redis.Conn) {
	r.Send("MULTI")
	fmt.Println(`g2 MULTI begin ...`)
	for i := 0; i < 5; i++ {
		if _, err := redis.String(r.Do("get", "hello")); err != nil {
			fmt.Println(err)
		}
		fmt.Println(`g2 now work... `)
	}
	time.Sleep(1 * time.Second)
	g, _ := r.Do("EXEC")
	fmt.Println(`g2 MULTI end ...`, g)
	// Done:相当于Add(-1)
	w.Done()
}

func main() {
	// Add:添加或者减少等待goroutine的数量

	w.Add(2)
	runtime.GOMAXPROCS(runtime.NumCPU())
	var rc1 redis.Conn = newRdsPool(`10.42.0.23:6379`, `sOd3bZBFgdVyGRWC`).Get()
	var rc2 redis.Conn = newRdsPool(`10.42.0.23:6379`, `sOd3bZBFgdVyGRWC`).Get()
	defer rc1.Close()
	defer rc2.Close()
	go g1(rc1)
	go g2(rc2)
	// Wait:执行阻塞，直到所有的WaitGroup数量变成0
	w.Wait()
}
